home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
doom
/
ldhe-src.0
/
ldhe-src
/
dehacked
/
source
/
x11_graphics.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-09
|
17KB
|
686 lines
// The X11 graphics module:
// There are lots of bugs and omissions in this code, but hey! It works! :)
#include <stdio.h>
#include <string.h>
#include "graphics.h"
#include "pc8x8.font"
X11_Graphics:: X11_Graphics()
{
keyboard = new X11_Keyboard(&display);
cursor_on = 1;
display = NULL;
xwindow = NULL;
}
X11_Graphics:: ~X11_Graphics()
{
if ( display )
set_grmode(TEXT25);
}
int
X11_Graphics:: ibm_charset(void)
{
return(1);
}
void
X11_Graphics:: flush(void)
{
if ( mode == TEXT25 ) {
TTY_Graphics::flush();
return;
}
XFlush(display);
}
void
X11_Graphics:: setcursor(int on)
{
if ( cursor_on == on ) {
// Nothing to do. :)
return;
}
if ( mode != TEXT50 ) {
TTY_Graphics::setcursor(on);
return;
}
cursor_on = on;
XPutImage(display, MainWin, cursor_gc, vga_cursor, 0, 0,
(cursor.x-1)*FONT_WIDTH, (cursor.y-1)*FONT_HEIGHT,
FONT_WIDTH, FONT_HEIGHT);
}
void
X11_Graphics:: set_default_colors(void)
{
if ( mode == TEXT25 ) {
TTY_Graphics::set_default_colors();
return;
}
fg = vga_colors[X11_WHITE+8];
bg = vga_colors[X11_BLACK+8];
XSetForeground(display, gc, fg);
XSetBackground(display, gc, bg);
}
void
X11_Graphics:: set_colors(int bright, int foreground, int background)
{
if ( mode == TEXT25 ) {
TTY_Graphics::set_colors(bright, foreground, background);
return;
}
if ( bright == BRIGHT )
bright = 8;
else
bright = 0;
switch (background) {
case BLACK: bg = vga_colors[X11_BLACK];
break;
case BLUE: bg = vga_colors[X11_BLUE];
break;
case GREEN: bg = vga_colors[X11_GREEN];
break;
case CYAN: bg = vga_colors[X11_CYAN];
break;
case RED: bg = vga_colors[X11_RED];
break;
case MAGENTA: bg = vga_colors[X11_MAGENTA];
break;
case YELLOW: bg = vga_colors[X11_YELLOW];
break;
case WHITE: bg = vga_colors[X11_WHITE];
break;
default: // What color was that??
bg = vga_colors[X11_BLACK];
break;
}
XSetBackground(display, gc, bg);
switch (foreground) {
case BLACK: fg = vga_colors[X11_BLACK+bright];
break;
case BLUE: fg = vga_colors[X11_BLUE+bright];
break;
case GREEN: fg = vga_colors[X11_GREEN+bright];
break;
case CYAN: fg = vga_colors[X11_CYAN+bright];
break;
case RED: fg = vga_colors[X11_RED+bright];
break;
case MAGENTA: fg = vga_colors[X11_MAGENTA+bright];
break;
case YELLOW: fg = vga_colors[X11_YELLOW+bright];
break;
case WHITE: fg = vga_colors[X11_WHITE+bright];
break;
default: // What color was that??
fg = vga_colors[X11_BLACK+bright];
break;
}
XSetForeground(display, gc, fg);
}
void
X11_Graphics:: clear(void)
{
if ( mode == TEXT25 ) {
TTY_Graphics::clear();
return;
}
clr_grscreen();
}
void
X11_Graphics:: clrbox(int x, int y, int width, int height)
{
if ( mode == TEXT25 ) {
TTY_Graphics::clrbox(x, y, width, height);
return;
}
if ( mode == GRAPHICS )
return;
XSetForeground(display, gc, bg);
XFillRectangle(display, MainWin, gc,
(x-1)*FONT_WIDTH, (y-1)*FONT_HEIGHT,
width*FONT_WIDTH, height*FONT_HEIGHT);
XSetForeground(display, gc, fg);
}
void
X11_Graphics:: clreol(void)
{
if ( mode == TEXT25 ) {
TTY_Graphics::clreol();
return;
}
if ( mode == GRAPHICS )
return;
for ( int i=cursor.x; i<=80; ++i )
X11_Graphics::putch(' ');
}
void
X11_Graphics:: gotoxy(int x, int y)
{
if ( mode == TEXT25 ) {
TTY_Graphics::gotoxy(x,y);
return;
}
if ( mode == GRAPHICS )
return;
if ( cursor_on ) {
XPutImage(display, MainWin, cursor_gc, vga_cursor, 0, 0,
(cursor.x-1)*FONT_WIDTH, (cursor.y-1)*FONT_HEIGHT,
FONT_WIDTH, FONT_HEIGHT);
}
cursor.x=x;
cursor.y=y;
if ( cursor_on ) {
XPutImage(display, MainWin, cursor_gc, vga_cursor, 0, 0,
(cursor.x-1)*FONT_WIDTH, (cursor.y-1)*FONT_HEIGHT,
FONT_WIDTH, FONT_HEIGHT);
}
}
void
X11_Graphics:: putch(int ch)
{
if ( mode == TEXT25 ) {
TTY_Graphics::putch(ch);
return;
}
if ( mode == GRAPHICS )
return;
XPutImage(display, MainWin, gc, pc8x8[(unsigned char)ch], 0, 0,
(cursor.x-1)*FONT_WIDTH, (cursor.y-1)*FONT_HEIGHT,
FONT_WIDTH, FONT_HEIGHT);
if ( cursor.x < 80 )
++cursor.x;
else if ( cursor.y < 50 ) {
++cursor.y;
cursor.x=1;
}
if ( cursor_on ) {
XPutImage(display, MainWin, cursor_gc, vga_cursor, 0, 0,
(cursor.x-1)*FONT_WIDTH, (cursor.y-1)*FONT_HEIGHT,
FONT_WIDTH, FONT_HEIGHT);
}
}
int
X11_Graphics:: has_graphics(void)
{
return(1);
}
void
X11_Graphics:: set_grmode(int newmode)
{
XColor Orig_colors[256], Blank_colors[256];
int i;
checkmode:
switch (newmode) {
case TEXT25: if ( mode == TEXT25 )
return;
XCloseDisplay(display);
display=NULL;
break;
case TEXT50: if ( mode == TEXT50 )
return;
// If we were in a graphics window...
if ( mode == GRAPHICS ) {
if ( ! xwindow )
break;
/* Smoothly blank and restore text50 */
for ( i=0; i<256; ++i )
Orig_colors[i].pixel = i;
XQueryColors(display, vis_colormap,
Orig_colors, 256);
memcpy(Blank_colors, Orig_colors,
256 * sizeof(XColor));
for ( i=0; i<256; ++i ) {
Blank_colors[i].red = 0;
Blank_colors[i].green = 0;
Blank_colors[i].blue = 0;
}
XStoreColors(display, vis_colormap,
Blank_colors, 256);
XPutImage(display,MainWin,gc,xwindow,
0, 0, 0, 0,
DISPLAY_WIDTH, DISPLAY_HEIGHT);
XSetWindowColormap(display, MainWin,
vga_colormap);
XStoreColors(display, vis_colormap,
Orig_colors, 256);
break;
}
// Create a window to play in...
if ( OpenMainWindow(TEXT50) != 0 )
return;
return;
case GRAPHICS: if ( mode == GRAPHICS )
return;
// If we were in TEXT50 mode, save the window.
if ( mode == TEXT50 ) {
if ( xwindow )
XDestroyImage(xwindow);
xwindow = XGetImage(display, MainWin,
0, 0,
DISPLAY_WIDTH, DISPLAY_HEIGHT,
AllPlanes, XYPixmap);
} else {
// Create a window to play in...
if ( OpenMainWindow(GRAPHICS) != 0 )
return;
}
// Set the visual colormap...
X11_Graphics::clr_grscreen();
if ( vis_colormap != ~0L ) {
XSetWindowColormap(display, MainWin,
vis_colormap);
}
XFlush(display);
break;
case LASTMODE: newmode = lastmode;
goto checkmode;
default: // Huh?
fprintf(stderr,
"Unknown graphics mode: 0x%.2x\n", newmode);
return;
}
lastmode = mode;
mode = newmode;
}
void
X11_Graphics:: set_colormap(struct color colormap[256])
{
int i;
XColor xcols[256];
if ( mode == TEXT25 ) {
return;
}
/* Create a custom visual colormap, if needed */
if ( vis_colormap == ~0L ) {
vis_colormap = XCreateColormap(display, MainWin,
DefaultVisual(display, XDefaultScreen(display)),
AllocAll);
}
/* Allocate custom colors... */
for(i=0;i<256;i++)
xcols[i].pixel = i;
XQueryColors(display, vis_colormap, xcols, 256);
for(i=0;i<256;i++) {
xcols[i].red = colormap[i].red<<8;
xcols[i].green = colormap[i].green<<8;
xcols[i].blue = colormap[i].blue<<8;
}
XStoreColors(display, vis_colormap, xcols, 256);
XSetWindowColormap(display, MainWin, vis_colormap);
}
void
X11_Graphics:: clr_grscreen(void)
{
if ( mode == TEXT25 ) {
return;
}
XSetForeground(display, gc, vga_colors[0]);
XSetBackground(display, gc, vga_colors[0]);
XFillRectangle(display,MainWin,gc,0,0,DISPLAY_WIDTH,DISPLAY_HEIGHT);
XSetForeground(display, gc, fg);
XSetBackground(display, gc, bg);
}
#if BYTE_ORDER == LITTLE_ENDIAN
void
X11_Graphics:: expand_8x8font(char smallfont[], char bigfont[])
{
char smask, bmask, bit;
int i, j;
// Assuming an 8x8 font...
for ( i=0; i<8; ++i ) {
bigfont[i*4] = 0x00;
for ( smask=0x01, bmask=0x03, j=0; j<4; ++j ) {
if ( smallfont[i]&smask ) {
bit = 0xFF;
} else {
bit = 0x00;
}
bigfont[i*4] |= (bit&bmask);
bmask <<= 2;
smask <<= 1;
}
bigfont[(i*4)+1] = 0x00;
for ( bmask=0x03, j=0; j<4; ++j ) {
if ( smallfont[i]&smask ) {
bit = 0xFF;
} else {
bit = 0x00;
}
bigfont[(i*4)+1] |= (bit&bmask);
bmask <<= 2;
smask <<= 1;
}
}
for ( i=0; i<8; ++i ) {
bigfont[(i*4)+2] = bigfont[i*4];
bigfont[(i*4)+3] = bigfont[(i*4)+1];
}
}
#else
void
X11_Graphics:: expand_8x8font(char smallfont[], char bigfont[])
{
char smask, bmask, bit;
int i, j;
// Assuming an 8x8 font...
for ( i=0; i<8; ++i ) {
bigfont[(i*4)+1] = 0x00;
for ( smask=0x01, bmask=0x03, j=0; j<4; ++j ) {
if ( smallfont[i]&smask ) {
bit = 0xFF;
} else {
bit = 0x00;
}
bigfont[(i*4)+1] |= (bit&bmask);
bmask <<= 2;
smask <<= 1;
}
bigfont[i*4] = 0x00;
for ( bmask=0x03, j=0; j<4; ++j ) {
if ( smallfont[i]&smask ) {
bit = 0xFF;
} else {
bit = 0x00;
}
bigfont[i*4] |= (bit&bmask);
bmask <<= 2;
smask <<= 1;
}
}
for ( i=0; i<8; ++i ) {
bigfont[(i*4)+2] = bigfont[i*4];
bigfont[(i*4)+3] = bigfont[(i*4)+1];
}
}
#endif /* Which Endian? */
void
X11_Graphics:: put_graphics_txt(int x, int y, char *string,
unsigned char color)
{
char big_char[8*4];
XImage *BIG_ch;
if ( mode != GRAPHICS ) {
return;
}
// Make sure we are still on the screen
y *= 2;
if ( y+(FONT_HEIGHT*2) > DISPLAY_HEIGHT )
return;
// Display the text...
XSetBackground(display, gc, vga_colors[0]);
XSetForeground(display, gc, color);
while ( *string ) {
// Make sure we have room to display
if ( x+(FONT_WIDTH*2) > DISPLAY_WIDTH )
return;
// Expand the font to 2x2 pixels per bit and display...
X11_Graphics::expand_8x8font(pc8x8_fontdata[*string], big_char);
BIG_ch=XCreateImage(display,
DefaultVisual(display, XDefaultScreen(display)),
1, XYBitmap, 0, big_char,
FONT_WIDTH*2, FONT_HEIGHT*2, 8, 2);
XPutImage(display, MainWin, gc, BIG_ch, 0, 0, x, y,
FONT_WIDTH*2, FONT_HEIGHT*2);
x += FONT_WIDTH*2;
++string;
}
}
void
X11_Graphics:: drawpoint(int x, int y, unsigned char color)
{
if ( mode != GRAPHICS ) {
return;
}
XSetForeground(display, gc, color);
XDrawPoint(display, MainWin, gc, x*2, y*2);
XDrawPoint(display, MainWin, gc, (x*2)+1, y*2);
XDrawPoint(display, MainWin, gc, x*2, (y*2)+1);
XDrawPoint(display, MainWin, gc, (x*2)+1, (y*2)+1);
}
void
X11_Graphics:: Map_Color(Colormap colormap, XColor *xcol)
{
/* Most of this code is adapted from 'xv' -- Thanks! :) */
int ri, gi, bi; /* The color shades we want */
int rd, gd, bd; /* The color shades we have */
int mdist, close, d; /* Distance and closest pixel */
int i, c;
XColor cmap[NUM_COLORS];
/* Read in the current display colormap */
for ( i=0; i<NUM_COLORS; ++i ) cmap[i].pixel = i;
XQueryColors(display, colormap, cmap, NUM_COLORS);
mdist = 1000000; close=0;
ri = (xcol->red >> 8);
gi = (xcol->green >> 8);
bi = (xcol->blue >> 8);
/* Cycle through the colors we have */
for ( c=0; c<NUM_COLORS; ++c ) {
rd = ri - (cmap[c].red >> 8);
gd = gi - (cmap[c].green >> 8);
bd = bi - (cmap[c].blue >> 8);
d = rd*rd + gd*gd + bd*bd;
if ( d < mdist ) {
mdist = d;
close = c;
}
}
/* Now try to allocate the closest color */
if ( XAllocColor(display, colormap, &cmap[close]) ) {
xcol->red = cmap[close].red;
xcol->green = cmap[close].green;
xcol->blue = cmap[close].blue;
xcol->pixel = cmap[close].pixel;
} else { /* What do we do here? */
/* Use it anyway -- Does it matter? :) */
xcol->red = cmap[close].red;
xcol->green = cmap[close].green;
xcol->blue = cmap[close].blue;
xcol->pixel = cmap[close].pixel;
}
}
int
X11_Graphics:: OpenMainWindow(int newmode)
{
char *window_Name = " Linux Doom Hack Editor ";
char *icon_Name = PROGNAME;
int i;
XWMHints wmhints;
XClassHint classhints;
XSizeHints sizehints;
XTextProperty windowName, iconName;
XSetWindowAttributes winattr;
XEvent event;
XColor xcol;
XGCValues gcv;
char *argv[2]={PROGNAME, NULL};
unsigned long valuemask;
/* The following is a bitmap for the X11 cursor */
char cursor_bitmap[] =
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
/* The following are almost IBM standard color codes, with some slight gamma
* correction for the dim colors to compensate for bright Xwindow screens.
*/
struct {
unsigned char r,g,b;
} crgb[16]={
{0x00,0x00,0x00},{0x18,0x18,0xB2},{0x18,0xB2,0x18},{0x18,0xB2,0xB2},
{0xB2,0x18,0x18},{0xB2,0x18,0xB2},{0xB2,0x68,0x18},{0xB2,0xB2,0xB2},
{0x68,0x68,0x68},{0x54,0x54,0xFF},{0x54,0xFF,0x54},{0x54,0xFF,0xFF},
{0xFF,0x54,0x54},{0xFF,0x54,0xFF},{0xFF,0xFF,0x54},{0xFF,0xFF,0xFF}};
/* Open our DISPLAY */
if ( !(display=XOpenDisplay(NULL)) ) {
fprintf(stderr, "X: Couldn't open display\n");
return(-1);
}
/* Make sure all is destroyed if killed off */
XSetCloseDownMode(display, DestroyAll);
/* Get the default colormap */
vga_colormap=DefaultColormap(display, XDefaultScreen(display));
/* Allocate custom colors... */
for(i=0;i<16;i++) {
xcol.red = crgb[i].r<<8;
xcol.green = crgb[i].g<<8;
xcol.blue = crgb[i].b<<8;
if (!XAllocColor(display, vga_colormap, &xcol)) {
/* Map color to one already on the display */
Map_Color(vga_colormap, &xcol);
}
vga_colors[i] = xcol.pixel;
}
vis_colormap = ~0L;
/* Create the main window */
MainWin = XCreateSimpleWindow(display,
RootWindow(display, DefaultScreen(display)), 0, 0,
DISPLAY_WIDTH, DISPLAY_HEIGHT, 0,
vga_colors[X11_WHITE], vga_colors[X11_WHITE]);
if (XStringListToTextProperty(&window_Name, 1, &windowName) == 0) {
fprintf(stderr, "Cannot create window name resource.");
return(-1);
}
if (XStringListToTextProperty(&icon_Name, 1, &iconName) == 0) {
fprintf(stderr, "Cannot create icon name resource.");
return(-1);
}
/* Various window manager settings */
wmhints.initial_state = NormalState;
wmhints.input = True;
wmhints.flags = StateHint | InputHint;
/* Set the class for xdhe */
classhints.res_name = PROGNAME;
classhints.res_class = PROGNAME;
/* Setup the max and minimum size that the window will be */
sizehints.flags = PSize | PMinSize | PMaxSize;
sizehints.min_width = DISPLAY_WIDTH;
sizehints.min_height = DISPLAY_HEIGHT;
sizehints.max_width = DISPLAY_WIDTH;
sizehints.max_height = DISPLAY_HEIGHT;
/* Now set the window manager properties */
XSetWMProperties(display, MainWin, &windowName, &iconName,
argv, 1, &sizehints, &wmhints, &classhints);
valuemask = CWColormap;
winattr.colormap = vga_colormap;
/* Check if the server allows backing store */
if (DoesBackingStore(XDefaultScreenOfDisplay(display)) == Always)
{
/* Ok we want backing store as it is very useful */
valuemask |= CWBackingStore;
winattr.backing_store = Always;
} else /* The keyboard handler needs to do refreshes */
keyboard->toggle_refresh(1);
XChangeWindowAttributes(display, MainWin, valuemask, &winattr);
/* Set up graphics contexts */
gcv.graphics_exposures = False;
if (!(gc = XCreateGC(display, MainWin, GCGraphicsExposures, &gcv))) {
fprintf(stderr, "X: Couldn't create graphics context.\n");
return(-1);
}
gcv.function = GXinvert;
if (!(cursor_gc = XCreateGC(display, MainWin,
(GCGraphicsExposures|GCFunction), &gcv))) {
fprintf(stderr, "X: Couldn't create graphics context.\n");
return(-1);
}
/* Initialize the font! */
for ( i=0; i<256; ++i ) {
pc8x8[i]=XCreateImage(display,
DefaultVisual(display, XDefaultScreen(display)),
1, XYBitmap, 0, pc8x8_fontdata[i],
FONT_WIDTH, FONT_HEIGHT, 8, 1);
}
vga_cursor=XCreateImage(display,
DefaultVisual(display, XDefaultScreen(display)),
1, XYBitmap, 0, cursor_bitmap,
FONT_WIDTH, FONT_HEIGHT, 8, 1);
Event_mask = KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask |
ExposureMask | StructureNotifyMask;
XSelectInput(display, MainWin, Event_mask);
/* Actually map the main window */
XMapWindow(display, MainWin);
/* Start up our VGA colormap */
XSetWindowColormap(display, MainWin, vga_colormap);
/* Loop, waiting for our window to be mapped */
do {
/* Get the next event */
XNextEvent(display, &event);
}
while (event.type != MapNotify);
/* Clear the display and show the cursor */
lastmode = mode;
mode = newmode;
clr_grscreen();
undercursor = NULL;
gotoxy(1, 1);
return(0);
}